﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using Finance;
using Finance.TodoSoft;
using Finance.Views;
using TodoSoft.Reporting;

namespace TodoSoft.Controls
{
	public partial class ReportViewer : UserControl
	{
		public ReportViewer()
		{
			_parametersControls = new Dictionary<string, Control>();
            
			InitializeComponent();
			_parametersPanel.Height = 0;
		}

		public TreeGrid TreeGrid { get { return _treeGrid; } }

		public event EventHandler<EventArgs> OnRefresh;

		private void OnDateTimeIntervalParameterControlPeriodChanged(object sender, EventArgs e)
		{
			RefreshReport();
		}

		private void RefreshReport()
		{
			Cursor.Current = Cursors.WaitCursor;
			try
			{
				OnRefresh.InvokeIfNotNull(this, EventArgs.Empty);

				if (Report != null && DataBase != null)
				{
					ExecuteReport();
				}

				TreeGrid.UpdateView();
			}
			finally
			{
				Cursor.Current = Cursors.Default;
			}
		}

		private void ExecuteReport()
		{
			var result = _reportExecuter.FillTreeGrid(DataBase.Sql, GetParametersValues());
			_treeGrid.TopLevelRows.Clear();
			_treeGrid.TopLevelRows.AddRange(result);
		}

		public DataBase DataBase { get; set; }

		public Report Report
		{
			get { return _report; }
			set
			{
				if (_report == value)
					return;

				_report = value;
				if (_report == null)
					return;

				_reportExecuter = new TreeGridReportExecuter(_report);
				_reportExecuter.CreateGroups();
				_reportExecuter.InitParameters(DataBase.Sql);

				foreach (var reportParameter in _report.Parameters)
				{
					AddParameter(reportParameter);
				}

				_treeGrid.SetGroupings(_reportExecuter.Groups);
				//Attach switch columns
				for (int index = _reportExecuter.Groups.Count - 2; index >= 0; index--)
				{
					_reportExecuter.Groups[index].Columns[0].CellClick += cell => _treeGrid.UpdateView();
				}
			}
		}

		private TreeGridReportExecuter _reportExecuter;

		private readonly Dictionary<string, Control> _parametersControls;
		private Report _report;

		public void AddParameter(ReportParameter parameter)
		{
			var periodParameter = parameter as PeriodReportParameter;
			if (periodParameter != null)
			{
				var control = new DateTimeIntervalControl {Parameter = periodParameter};
				control.PeriodChanged += OnDateTimeIntervalParameterControlPeriodChanged;
				_parametersControls.Add(periodParameter.Name, control);
				control.Dock = DockStyle.Top;
				_parametersPanel.Controls.Add(control);
				_parametersPanel.Height += control.Height;
				control.BringToFront();
				return;
			}
			
			throw new Exception("Invalid parameter type: " + parameter.GetType());
		}

		Dictionary<ReportParameter, object> GetParametersValues()
		{
			if (_report == null)
				return null;

			return _report.Parameters.ToDictionary(reportParameter => reportParameter, reportParameter => GetParameterValue(reportParameter.Name));
		}

		public object GetParameterValue(string parameterName)
		{
			if(!_parametersControls.ContainsKey(parameterName))
				throw new Exception("Parameter not found: " + parameterName);

			var parameterControl = _parametersControls[parameterName];

			var intervalParameterControl = parameterControl as DateTimeIntervalControl;
			if (intervalParameterControl != null)
			{
				return intervalParameterControl.DateTimeInterval;
			}

			throw new Exception("Can't get parameter value.");
		}

		private void menuItem1_Click(object sender, EventArgs e)
		{
			RefreshReport();
		}
	}
}	